package com.erju.config;

import com.erju.dao.UserMapper;
import com.erju.pojo.User;
import com.erju.utils.JWTToken;
import com.erju.utils.JWTUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * 写Shiro认证和授权的业务逻辑 自己定制化业务
 *
 * @author: 86132
 * @date: 2022.03.07
 */
@Component
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserMapper userMapper;

    /**
     * 根据token判断此Authenticator是否使用该realm
     * 必须重写不然shiro会报错
     *
     * @param token
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 授权 Authorization
     * 只有当需要检测用户权限的时候才会调用此方法，例如@RequiresRoles,@RequiresPermissions之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("授权~~~~~");
        String token = principals.toString();
        String username = JWTUtil.getUsername(token);
        //到数据库查权限
        User user = userMapper.selectByUserName(username);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //查询数据库来获取用户的角色
        info.addRole(String.valueOf(user.getUser_type()));
        //查询数据库来获取用户的权限
        info.addStringPermission(String.valueOf(user.getUser_type()));
        return info;
    }


    /**
     * 认证 Authentication
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可，在需要用户认证和鉴权的时候才会调用
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("认证~~~~~~~");
        String jwt = (String) token.getCredentials();
        String username = null;
        //解码时候出错，可能是token的长度和规定好的不一样了
        try {
            username = JWTUtil.getUsername(jwt);
        } catch (Exception e) {
            throw new AuthenticationException("token非法，不是规范的token，可能被篡改了，或者过期了");
        }
        if (!JWTUtil.verify(jwt) || username == null) {
            throw new AuthenticationException("token认证失效，token错误或者过期，重新登陆");
        }
        User user = userMapper.selectByUserName(username);
        if (user == null) {
            throw new AuthenticationException("该用户不存在");
        }
        return new SimpleAuthenticationInfo(jwt, jwt, "MyRealm");
    }
}
